import {Observable, from, of, mergeMap} from "rxjs";
import {tap} from 'rxjs/operators';

async function routerHandler() {
    console.log('pay...')
    return 'pay'
}

const context = {
    handle(): Observable<any> {
        return of('original result')
    }
}
const next = {
    handle(): Observable<any> {         //内容就是路由处理函数
        console.log('app.index...')
        for (let k = 0; k < 100; k++) {
            console.log(`for(let k=${k};k<100;k++)`)
        }
        return of('app.index')
    }
}

export class LoggerInterceptor {
    async intercept(context, next) {
        console.log('Before...');

        const now = Date.now();
        // next.handle 就是原方法
        return next.handle()
            .pipe(
                // tap在 handle执行后执行，传入一个函数该函数接收参数就是 原方法的返回值
                tap((handleValue) => {
                    console.log(handleValue)
                    console.log(`After... ${Date.now() - now}ms`)
                })
            )
    }
}

export class LoggerInterceptor2 {
    async intercept(context, next) {
        console.log('LoggerInterceptor2 Before...');

        const now = Date.now();
        // next.handle 就是原方法
        return next.handle()
            .pipe(
                // tap在 handle执行后执行，传入一个函数该函数接收参数就是 原方法的返回值
                tap((handleValue) => {
                    console.log(handleValue)
                    console.log(`LoggerInterceptor2 After... ${Date.now() - now}ms`)
                })
            )
    }
}

const loogger = new LoggerInterceptor();
const loogger2 = new LoggerInterceptor2();

// 2在前1在后
const interceptors = [loogger2, loogger];

function callInterceptors(interceptors) {
    const nextFn = (i = 0): any => {
        // i 大于 拦截器的长度说明拦截结束了
        if (i >= interceptors.length) {
            let result = routerHandler();
            return result instanceof Promise ? from(result) : of(result)
        }
        // 第一次拿到第一个拦截器，执行intercept方法
        const result = interceptors[i].intercept(
            null,
            {
                handle() {
                    return nextFn(i + 1)
                }
            }
        );
        return from(result).pipe(mergeMap(res => res instanceof Observable ? res : of(res)));
    }
    return nextFn();
}

callInterceptors(interceptors).subscribe(value=>{
    console.log(value)
})
